//
//  BizArchiveCache.m
//  BizClientKit
//
//  Created by Cool Camel on 17/4/23.
//  Copyright © 2017年 www.biz-united.com.cn. All rights reserved.
//

#import "FSArchiveCache.h"
//#import "BizCryptoUtility.h"

@interface FSArchiveCache()
@property (nonatomic, strong, readwrite, nullable) NSMutableDictionary * data;
@property (nonatomic, strong, readwrite, nullable) NSString * name;
@property (nonatomic, assign, readwrite) Biz_CACHE_TYPE type;
@end

@implementation FSArchiveCache
+ (BOOL)cacheIsExistWithName:(NSString *)name {
    
    NSMutableDictionary * keychainQuery = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                           (__bridge id)kSecClassGenericPassword,
                                           (__bridge id)kSecClass,name,
                                           (__bridge id)kSecAttrService,name,
                                           (__bridge id)kSecAttrAccount,
                                           (__bridge id)kSecAttrAccessibleAfterFirstUnlock,
                                           (__bridge id)kSecAttrAccessible,
                                           nil];
    
    NSMutableDictionary * ret = nil;
    
    [keychainQuery setObject:(id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData];
    [keychainQuery setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit];
    
    CFDataRef keyData = NULL;
    if (SecItemCopyMatching((__bridge CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr) {
        
        @try {
            
            ret = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData *)keyData];
        }
        @catch (NSException *e) {
            
            ret = nil;
        }
    }
    
    if (keyData) {
        
        CFRelease(keyData);
    }

    return (nil != ret);
}

+ (NSMutableDictionary *)keychainQueryWithName:(NSString *)name {
    
    return [NSMutableDictionary dictionaryWithObjectsAndKeys:
            (__bridge id)kSecClassGenericPassword,
            (__bridge id)kSecClass,name,
            (__bridge id)kSecAttrService,name,
            (__bridge id)kSecAttrAccount,
            (__bridge id)kSecAttrAccessibleAfterFirstUnlock,
            (__bridge id)kSecAttrAccessible,
            nil];
}

//- (instancetype)init {
//    
//    NSString * name = [FSArchiveCache makeUUID];
//    return [self initWithName:name];
//}

- (instancetype)initWithName:(NSString *)name {
    
    if(self = [super init]) {
        
        self.name = name;
        self.type = Biz_CACHE_TYPE_ARCHIVE;

        NSMutableDictionary * data = nil;
        NSMutableDictionary * keychainQuery = [FSArchiveCache keychainQueryWithName:name];
        [keychainQuery setObject:(id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData];
        [keychainQuery setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit];
        
        CFDataRef keyData = NULL;
        OSStatus result = SecItemCopyMatching((__bridge CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData);
        if(result == noErr) {
            
            @try {
                
                data = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData *)keyData];
            }
            @catch (NSException *e) {
                
                data = nil;
            }
        }
        
        if (keyData) {
            
            CFRelease(keyData);
        }
        
        if(!data) {
        
            data = [NSMutableDictionary dictionary];
            NSMutableDictionary * keychianQueryForAdd = [FSArchiveCache keychainQueryWithName:name];
            //Delete old item before add new item
            SecItemDelete((__bridge CFDictionaryRef)keychainQuery);
            //Add new object to search dictionary(Attention:the data format)
            [keychianQueryForAdd setObject:[NSKeyedArchiver archivedDataWithRootObject:data]
                                    forKey:(__bridge id)kSecValueData];
            //Add item to keychain with the search dictionary
            OSStatus result = SecItemAdd((__bridge CFDictionaryRef)keychianQueryForAdd, NULL);
            
            if(result != noErr)
                return nil;
        }
        
        self.data = data;
    }
    
    return self;
}

- (void)dealloc {
    
}

- (BOOL)updateWithKey:(NSString *)key Object:(id)object {
    
    [self.data setValue:object forKey:key];
    NSMutableDictionary * keychainQuery = [FSArchiveCache keychainQueryWithName:self.name];
    //Delete old item before add new item
    SecItemDelete((__bridge CFDictionaryRef)keychainQuery);
    //Add new object to search dictionary(Attention:the data format)
    [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:self.data]
                      forKey:(__bridge id)kSecValueData];
    //Add item to keychain with the search dictionary
    OSStatus result = SecItemAdd((__bridge CFDictionaryRef)keychainQuery, NULL);
    return (result == noErr);
}


- (BOOL)deleteWithKey:(NSString *)key {
    
    [self.data removeObjectForKey:key];
    NSMutableDictionary * keychainQuery = [FSArchiveCache keychainQueryWithName:self.name];
    //Delete old item before add new item
    SecItemDelete((__bridge CFDictionaryRef)keychainQuery);
    //Add new object to search dictionary(Attention:the data format)
    [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:self.data]
                      forKey:(__bridge id)kSecValueData];
    //Add item to keychain with the search dictionary
    OSStatus result = SecItemAdd((__bridge CFDictionaryRef)keychainQuery, NULL);
    return (result == noErr);
}

- (id)loadObjectWithKey:(NSString *)key {

    return [self.data valueForKey:key];
}

- (NSDictionary<NSString *,NSDictionary *> *)allObjects {

    return [NSDictionary dictionaryWithDictionary:self.data];
}
@end
